package com.htfyun.hardware;

import android.hardware.htfyun.IHallStateChangedListener;
import android.hardware.htfyun.IHallStateService;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.util.Log;

import com.htfyun.hardware.reflect.Utils;

import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class HallStateController {
    private static final String TAG = "HallStateController";

    private static HallStateController sInstance = null;
    private IHallStateService mService = null;

    private final Map<OnHallStateChangedListener, Handler> mListenerMap = new ConcurrentHashMap<>();

    private HallStateChangedListener mHallStateChangedListener;

    public interface OnHallStateChangedListener {
        void onHallStateChangedListener(boolean isHallOn);
    }

    private HallStateController() {
        IBinder binder = Utils.getSystemServiceReflect("hallStateService");
        if (binder == null) {
            Log.e(TAG, "Could not retrieve hallStateService");
            return;
        }
        mService = IHallStateService.Stub.asInterface(binder);
    }

    public static synchronized HallStateController getInstance() {
        if (sInstance == null) {
            sInstance = new HallStateController();
        }
        return sInstance;
    }

    public void registerHallStateChangedListener(OnHallStateChangedListener listener) {
        registerHallStateChangedListener(listener, null);
    }

    public void registerHallStateChangedListener(OnHallStateChangedListener listener, Handler handler) {
        if (mService == null) {
            return;
        }
        if (handler == null) {
            Looper looper = Looper.myLooper();
            if (looper == null) {
                throw new IllegalArgumentException(
                        "No handler given, and current thread has no looper!");
            }
            handler = new Handler(looper);
        }

        Log.i(TAG, "registerHallStateChangedListener");
        mListenerMap.put(listener, handler);

        if (mHallStateChangedListener == null) {
            mHallStateChangedListener = new HallStateChangedListener();
            try {
                mService.registerHallStateChangedListener(mHallStateChangedListener);
            } catch (RemoteException e) {
                Log.e(TAG, "RemoteException in registerHallStateChangedListener", e);
                mHallStateChangedListener = null;
            }
        }
    }

    public void unregisterHallStateChangedListener(OnHallStateChangedListener listener) {

        if (mService == null) {
            return;
        }

        Log.i(TAG, "unregisterHallStateChangedListener listener = " + listener);
        mListenerMap.remove(listener);

        Log.e(TAG, "mListenerMap count = " + mListenerMap.size());

        if (mListenerMap.isEmpty()) {
            if (mHallStateChangedListener != null) {
                try {
                    mService.unregisterHallStateChangedListener(mHallStateChangedListener);
                } catch (RemoteException e) {
                    Log.e(TAG, "RemoteException in unregisterKeyEventListener", e);
                } finally {
                    mHallStateChangedListener = null;
                }
            }
        }
    }

    public boolean isHallOn() {
        if (mService == null) {
            return false;
        }
        try {
            return mService.isHallOn();
        } catch (RemoteException e) {
            e.printStackTrace();
        }

        return false;
    }

    private void actionOnHallStateChanged(final boolean hallOn) {

        Iterator<Map.Entry<OnHallStateChangedListener, Handler>> it = mListenerMap.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<OnHallStateChangedListener, Handler> entry = it.next();
            Handler handler = entry.getValue();
            final OnHallStateChangedListener l = entry.getKey();
            if (handler != null && l != null) {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        l.onHallStateChangedListener(hallOn);
                    }
                });
            }
        }
    }


    private class HallStateChangedListener extends IHallStateChangedListener.Stub {

        @Override
        public IBinder asBinder() {
            return this;
        }

        @Override
        public void onHallStateChanged(boolean hallOn) throws RemoteException {
            actionOnHallStateChanged(hallOn);
        }
    }
}
